package com.thinvent.remotepassword.util;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.huaban.analysis.jieba.JiebaSegmenter;
import com.huaban.analysis.jieba.SegToken;
import com.huaban.analysis.jieba.WordDictionary;
import com.thinvent.remotepassword.entity.WikiDocData;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

public class JiebaTokenizer {

    private static final List<String> stopWords = Arrays.asList(
            "你好", "的", "了", "呢", "吗", "啊", "吧", "呀", "着", "就", "在", "是", "给", "了",
            "时候", "一直", "显示", "不", "正确", "我们", "是不是", "其他", "但是", "里面", "有", "里", " "
    );

    private static final List<String> punctuations = Arrays.asList("，", "。", "！", "？", "；", "：", "‘", "’", "“", "”", "（", "）", "《", "》", "〈", "〉", "【", "】", "、", "—", "…");

    public static List<String> tokenizeMain(String text) {
        // 加载自定义词列表
        loadCustomWords();

        List<String> tokens = tokenize(text);
        List<String> filteredTokens = filterTokens(tokens);
        return filteredTokens;
    }

    public static void main(String[] args) throws IOException {
//        String text = "重大项目库里面，我们有中央预算内投资，有其他地方财政性建设资金。但是填报已完成投资里面，我们的其他地方财政性建设资金是不是填到其他类别汇总里。 ";
        String text = "无法打开重大库";
        System.out.println("客户问题：" + text);
        // 分词
        List<String> strings = tokenizeMain(text);
        System.out.println("客户问题分词后的结果（去除了标点符号、助词、助动词、语气词；只留下关键字）：" + strings);
        // 将分词后的list与数据库中的数据进行对比（案例展示，使用Javamock数据 并不是真实的数据库数据）
        List<WikiDocData> wikiDocData = getWikiDocData();
        List<WikiDocData> resultList = new ArrayList<>();
        // 对比
        for (String keyword : strings) {
            for (WikiDocData data : wikiDocData) {
                String prompt = SimilarityUtil.getVet(keyword);
                String question = SimilarityUtil.getVet(data.getQuestion());
                // 对比相似度
                double v = SimilarityUtil.cosineSimilarity(SimilarityUtil.strToDoubleArray(prompt), SimilarityUtil.strToDoubleArray(question));
                if(v >= 0.6) {
                    System.out.println("问题：" + keyword + "，匹配到的问题：" + data.getQuestion() + "，得分：" + v);
                    resultList.add(data);
                }
            }
        }
        // 去重
        Set<WikiDocData> uniqueData = new HashSet<>(resultList);
        resultList = new ArrayList<>(uniqueData);
        System.out.println("匹配的结果：" + JSON.toJSONString(resultList));
    }

    public static List<WikiDocData> getWikiDocData() {
        String jsonData = "[\n" +
                "    {\n" +
                "        \"id\": \"1\",\n" +
                "        \"question\": \"修改密码\",\n" +
                "        \"answer\": \"修改密码答案\",\n" +
                "        \"docId\": \"doc1\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"id\": \"2\",\n" +
                "        \"question\": \"调度任务填写\",\n" +
                "        \"answer\": \"注册登录答案\",\n" +
                "        \"docId\": \"doc2\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"id\": \"3\",\n" +
                "        \"question\": \"后台修改密码\",\n" +
                "        \"answer\": \"后台是否修改了密码答案\",\n" +
                "        \"docId\": \"doc3\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"id\": \"4\",\n" +
                "        \"question\": \"项目申报\",\n" +
                "        \"answer\": \"已经报送的项目需要撤回答案\",\n" +
                "        \"docId\": \"doc4\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"id\": \"5\",\n" +
                "        \"question\": \"打捆项目推送操作\",\n" +
                "        \"answer\": \"打捆项目推送操作答案\",\n" +
                "        \"docId\": \"doc5\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"id\": \"6\",\n" +
                "        \"question\": \"地方财政性建设资金\",\n" +
                "        \"answer\": \"地方财政性建设资金答案\",\n" +
                "        \"docId\": \"doc6\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"id\": \"7\",\n" +
                "        \"question\": \"地方指标填写操作\",\n" +
                "        \"answer\": \"地方指标填写操作答案\",\n" +
                "        \"docId\": \"doc7\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"id\": \"8\",\n" +
                "        \"question\": \"投资情况校验失败\",\n" +
                "        \"answer\": \"投资情况校验失败答案\",\n" +
                "        \"docId\": \"doc8\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"id\": \"9\",\n" +
                "        \"question\": \"滚动计划推送操作\",\n" +
                "        \"answer\": \"滚动计划推送操作答案\",\n" +
                "        \"docId\": \"doc9\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"id\": \"10\",\n" +
                "        \"question\": \"未收到重置密码的邮件\",\n" +
                "        \"answer\": \"未收到重置密码的邮件答案\",\n" +
                "        \"docId\": \"doc10\",\n" +
                "        \"createTime\": \"2024-08-05 10:00:00\",\n" +
                "        \"updateTime\": \"2024-08-05 10:00:00\"\n" +
                "    }\n" +
                "]";

        ObjectMapper mapper = new ObjectMapper();
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        try {
            List<WikiDocData> dataList = mapper.readValue(jsonData, new TypeReference<List<WikiDocData>>(){});

            // Print the mock data
            for (WikiDocData data : dataList) {
                System.out.println(JSON.toJSONString(data));
            }
            return dataList;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void loadCustomWords() {
        // 直接在代码中维护不拆分的词列表
        List<String> customWords = Arrays.asList("不正确", "改密码", "修改密码", "注册登录", "填写前期项目", "储备级别", "接收处室", "重大项目库", "中央预算内", "地方财政性", "建设资金", "已完成投资", "其他类别"
        , "项目库", "显示原密码", "后台改密码", "中央预算内投资", "地方财政性建设资金", "重大库");

        try {
            // 创建一个临时文件
            Path tempFile = Files.createTempFile("jieba_custom_dict", ".txt");

            // 将自定义词写入临时文件
            Files.write(tempFile, customWords.stream()
                    .map(word -> word + " 10 userDefine")
                    .collect(Collectors.toList()));

            // 加载自定义词典
            WordDictionary.getInstance().loadUserDict(tempFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static List<String> tokenize(String text) {
        JiebaSegmenter segmenter = new JiebaSegmenter();

        // 使用搜索引擎模式进行分词
        List<SegToken> tokens = segmenter.process(text, JiebaSegmenter.SegMode.SEARCH);

        // 提取词语
        return tokens.stream()
                .map(token -> token.word)
                .collect(Collectors.toList());
    }

    public static List<String> filterTokens(List<String> tokens) {
        // 过滤掉助词、助动词和标点符号
        return tokens.stream()
                .filter(token -> !stopWords.contains(token))
                .filter(token -> !isPunctuation(token))
                .collect(Collectors.toList());
    }

    private static boolean isPunctuation(String token) {
        return punctuations.contains(token) || token.matches("\\p{Punct}");
    }

}
